package com.zmn.uac.business.template.oauth.login;

import com.alibaba.fastjson.JSONObject;
import com.zmn.common.dto2.ResponseDTO;
import com.zmn.common.utils.string.StringUtil;
import com.zmn.saas.common.dro.app.AppInfoDRO;
import com.zmn.saas.dubbo.dto.app.AppDRO;
import com.zmn.uac.business.interfaces.channel.ChannelBService;
import com.zmn.uac.business.interfaces.oauth.login.LoginBaseBService;
import com.zmn.uac.business.interfaces.user.UserCenterBService;
import com.zmn.uac.business.interfaces.user.UserInfoBService;
import com.zmn.uac.client.*;
import com.zmn.uac.common.dio.oauth.login.TempCodeDIO;
import com.zmn.uac.common.dio.oauth.login.UserAuthLoginDIO;
import com.zmn.uac.common.dro.oauth.login.UserAuthLoginDRO;
import com.zmn.uac.common.entity.oauth.login.*;
import com.zmn.uac.common.entity.oauth.phone.UserPhoneInfo;
import com.zmn.uac.common.info.UserAuthPhoneInfo;
import com.zmn.uac.model.bo.user.UserThirdInfoRegisterBO;
import com.zmn.uac.util.LogAlibabaUtil;
import com.zmn.uuc.common.dio.user.UserBindMobileNoCaptchaByUserIdDIO;
import com.zmn.uuc.common.dio.user.UserLoginByThirdDIO;
import com.zmn.uuc.common.dro.user.UserThirdBaseDRO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Objects;


/**
 * 类描述：登录模板模式基类
 *
 * @author xujie
 * @since 2021/06/08 15:56
 */
@Slf4j
@Component
public abstract class BaseLoginTemplateMode implements LoginBaseBService {

    private static final String TAG = "登录模板模式基类";

    @Resource
    UserCenterBService userCenterBusinessService;

    @Resource
    UserInfoBService userInfoBusinessService;

    @Resource
    ChannelBService channelBusinessService;

    @Resource
    UserThirdListClient userThirdListClient;

    @Resource
    UserModifyClient userModifyClient;

    @Resource
    UserLoginClient userLoginClient;

    @Resource
    UserBindClient userBindClient;

    /**
     * 三方用户数据获取
     *
     * @param dio           用户授权登陆请求对象
     * @param authPhoneInfo 用户授权手机号加密信息
     * @return 用户授权登陆信息
     * @author xujie
     * @since 2021/06/09
     */
    public abstract ResponseDTO<UserAuthLoginInfo> thirdPartyUserDataAcquisition(UserAuthLoginDIO dio, UserAuthPhoneInfo authPhoneInfo);

    /**
     * 获取三方平台的openId
     *
     * @param tempCodeDIO
     * @return
     * @author liubodong
     * @since 2021/07/09
     */
    public abstract ResponseDTO<String> getThirdPartyOpenIdByCode(TempCodeDIO tempCodeDIO, AppDRO app);

    /**
     * 登陆
     *
     * @param dio           用户授权登陆参数
     * @param authPhoneInfo 用户授权手机号加密信息
     * @return ResponseDTO<UserAuthLoginDRO>
     * @author xujie
     * @since 2021/05/18
     */
    @Override
    public ResponseDTO<UserAuthLoginDRO> login(UserAuthLoginDIO dio, UserAuthPhoneInfo authPhoneInfo) {

        ResponseDTO<UserAuthLoginInfo> response = thirdPartyUserDataAcquisition(dio, authPhoneInfo);
        if (!response.isSuccess()) {
            return ResponseDTO.fail(response.getMessage());
        }
        UserAuthLoginInfo userAuthLoginInfo = response.getData();
        UserInfo userInfo = userAuthLoginInfo.getUserInfo();
        UserOtherInfo userOtherInfo = userAuthLoginInfo.getUserOtherInfo();
        PlatInfo platInfo = userAuthLoginInfo.getPlatInfo();
        ThirdAppInfo thirdAppInfo = userAuthLoginInfo.getThirdAppInfo();
        UserPhoneInfo userPhoneInfo = userAuthLoginInfo.getUserPhoneInfo();
        Long userId;
        boolean newUser;

        UserThirdBaseDRO thirdBase = userThirdListClient.getThirdByOpenIdAndAppIdAndMobile(userInfo.getOpenId(), thirdAppInfo.getAppId(), userPhoneInfo.getMobile());
        if (Objects.nonNull(thirdBase)) {
            userId = thirdBase.getUserId();
            updateAuthUserNickNameAndAvatarUrl(thirdBase, userInfo.getNickName(), userInfo.getAvatarSrc());
            newUser = false;
        } else {
            UserThirdInfoRegisterBO userRegisterBO = new UserThirdInfoRegisterBO();
            BeanUtils.copyProperties(userInfo, userRegisterBO);
            BeanUtils.copyProperties(userOtherInfo, userRegisterBO);
            BeanUtils.copyProperties(platInfo, userRegisterBO);
            BeanUtils.copyProperties(thirdAppInfo, userRegisterBO);
            BeanUtils.copyProperties(userPhoneInfo, userRegisterBO);
            log.info("[{}], {}, {}三方信息注册请求参数:{}", TAG, dio.getUuid(), thirdAppInfo.getAppName(), userRegisterBO);
            ResponseDTO<Long> registerDTO = userCenterBusinessService.registerUserThird(userRegisterBO);
            log.info("[{}], {}, {}三方信息注册响应参数:{}", TAG, dio.getUuid(), thirdAppInfo.getAppName(), registerDTO);
            if (!registerDTO.isSuccess() || Objects.isNull(registerDTO.getData())) {
                return ResponseDTO.fail(registerDTO.getMessage());
            }
            userId = registerDTO.getData();
            newUser = true;
        }
        // 第三方账号登录
        dio.setEntrance(platInfo.getEntrance());
        dio.setThirdAppId(thirdAppInfo.getAppId());
        dio.setUserId(userId);
        dio.setOpenId(userInfo.getOpenId());
        dio.setUnionId(userInfo.getUnionId());
        dio.setAppName(thirdAppInfo.getAppName());
        dio.setChannelName(thirdAppInfo.getAppName());
        if (StringUtil.isNotBlank(userPhoneInfo.getMobile())) {
            dio.setMobile(userPhoneInfo.getMobile());
        }
        log.info("[{}],{},获取用户登录信息入参：{}", TAG, dio.getUuid(), dio);
        ResponseDTO<UserAuthLoginDRO> responseUserAuthLogin = getUserAuthLoginInfo(dio, thirdAppInfo.getAppId());
        log.info("[{}],{},获取用户登录信息出参：{}", TAG, dio.getUuid(), JSONObject.toJSONString(responseUserAuthLogin));
        if (!responseUserAuthLogin.isSuccess()) {
            log.error("[{}], 获取用户登录信息失败：{}", TAG, JSONObject.toJSONString(responseUserAuthLogin));
            return ResponseDTO.fail(responseUserAuthLogin.getMessage());
        }
        UserAuthLoginDRO userAuthLogin = responseUserAuthLogin.getData();
        if (StringUtil.isBlank(userAuthLogin.getMobile()) && StringUtil.isNotBlank(userPhoneInfo.getMobile())) {
            // 绑定手机号
            UserBindMobileNoCaptchaByUserIdDIO bindMobileNoCodeByUserId = new UserBindMobileNoCaptchaByUserIdDIO();
            bindMobileNoCodeByUserId.setUserId(userAuthLogin.getUserId());
            bindMobileNoCodeByUserId.setMobile(userPhoneInfo.getMobile());

            Boolean bindStatus = userBindClient.bindMobileNoCaptchaByUserId(bindMobileNoCodeByUserId);
            if(bindStatus){
                userAuthLogin.setMobile(userPhoneInfo.getMobile());
            }
        }
        userAuthLogin.setNewUser(newUser);

        log.info("大数据日志打印到特定服务上" +
                "dio={}," +
                "userInfo={}," +
                "thirdAppInfo={}," +
                "userPhoneInfo={}," +
                "userAuthLogin={}," +
                "thirdBase={}," +
                "authPhoneInfo={}",dio,userInfo,thirdAppInfo,userPhoneInfo,userAuthLogin,thirdBase,authPhoneInfo);
        LogAlibabaUtil.loginLog(dio,userInfo,platInfo,thirdAppInfo,userPhoneInfo,userAuthLogin,thirdBase,authPhoneInfo);
        return ResponseDTO.success(userAuthLogin);
    }

    @Override
    public ResponseDTO<String> getOpenIdByCode(TempCodeDIO tempCodeDIO) {
        Integer channelId = tempCodeDIO.getChannelId();
        AppDRO app = getAppByChannelId(channelId);
        if (Objects.isNull(app)) {
            return ResponseDTO.fail("查询应用为null");
        }
        return getThirdPartyOpenIdByCode(tempCodeDIO, app);
    }

    /**
     * 更新授权用户昵称、头像信息
     *
     * @param userThirdBase userThirdBase
     * @param nickName      nickName
     * @param avatar        avatar
     */
    protected void updateAuthUserNickNameAndAvatarUrl(UserThirdBaseDRO userThirdBase, String nickName, String avatar) {

        log.info("[{}], 更新授权用户昵称、头像信息参数userThirdBaseDRO:{}, nickName:{}, avatar:{}", TAG, userThirdBase, nickName, avatar);
        if (StringUtils.isNotBlank(nickName) && !nickName.equals(userThirdBase.getNickName())) {
            userModifyClient.modifyNickNameByUserId(userThirdBase.getUserId(), nickName);
        }
        if (StringUtils.isNotBlank(avatar) && !avatar.equals(userThirdBase.getAvatarSrc())) {
            userModifyClient.modifyAvatarSrcByUserId(userThirdBase.getUserId(), avatar);
        }
    }

    /**
     * 登陆
     *
     * @param dio dio
     * @return UserAuthLoginDRO
     * @author xujie
     * @since 2021/05/19
     */
    protected ResponseDTO<UserAuthLoginDRO> getUserAuthLoginInfo(UserAuthLoginDIO dio, String appId) {
        Long userId = dio.getUserId();
        // 三方信息登陆获取token
        UserLoginByThirdDIO userLoginByThird = setUserLoginByThirdDIO(dio);
        String token = userLoginClient.loginByThirdAccount(userLoginByThird);
        // 获取用户信息
        UserThirdBaseDRO thirdBase = userThirdListClient.getThirdByOpenIdAndAppIdAndMobile(dio.getOpenId(), appId, dio.getMobile());
        if (Objects.nonNull(thirdBase)) {
            userId = thirdBase.getUserId();
        }
        return userInfoBusinessService.getUserInfoByTokenAndUserId(token, userId, dio.getOpenId());
    }


    /**
     * 获取渠道名称
     *
     * @param channelId 渠道id
     * @return 渠道名称
     * @author xujie
     * @since 2021/05/19
     */
    public String getNameByChannelId(Integer channelId) {
        return channelBusinessService.getNameByChannelId(channelId);
    }


    /**
     * 通过渠道ID获取应用配置
     *
     * @param channelId 渠道id
     * @return 应用配置
     * @author xujie
     * @since 2021/05/19
     */
    protected AppDRO getAppByChannelId(Integer channelId) {
        return channelBusinessService.getAppByChannelId(channelId);
    }


    /**
     * 通过店铺ID获取应用配置
     *
     * @param shopId 店铺id
     * @return 应用配置
     * @author xujie
     * @since 2021/05/19
     */
    protected AppDRO getAppInfoByShopId(Integer shopId) {
        return channelBusinessService.getAppInfoByShopId(shopId);
    }


    /**
     * 通过渠道ID获取应用配置
     *
     * @param channelId 渠道id
     * @return 应用配置
     * @author xujie
     * @since 2021/08/12
     */
    protected AppInfoDRO getThirdAppByChannelId(Integer channelId, Integer shopId) {
        return channelBusinessService.getShowAppByChannelIdOrShopId(channelId, shopId);
    }


    /**
     * 设置UserLoginByThird
     * @param dio
     * @return
     */
    private UserLoginByThirdDIO setUserLoginByThirdDIO(UserAuthLoginDIO dio){
        UserLoginByThirdDIO userLoginByThird = new UserLoginByThirdDIO();
        userLoginByThird.setPlat(dio.getPlat());
        userLoginByThird.setChannelId(dio.getChannelId());
        userLoginByThird.setOpenId(dio.getOpenId());
        userLoginByThird.setDeviceInfo(dio.getDeviceInfo());
        userLoginByThird.setIp(dio.getIp());
        userLoginByThird.setEntrance(dio.getEntrance());
        userLoginByThird.setAppId(dio.getThirdAppId());
        userLoginByThird.setAppName(dio.getAppName());
        userLoginByThird.setChannelName(dio.getChannelName());
        userLoginByThird.setMobile(dio.getMobile());

        return userLoginByThird;
    }
}
